# Copyright (C) 2010-2013 Cuckoo Sandbox Developers.
# Copyright (C) 2012 JoseMi Holguin (@j0sm1)
# This file is part of Cuckoo Sandbox - http://www.cuckoosandbox.org
# See the file 'docs/LICENSE' for copying permission.

"""IRC Protocol"""

import cStringIO
import re
import logging

from lib.dragon.common.utils import convert_to_printable

class ircMessage(object):
    """IRC Protocol Request."""

    # client commands
    __methods_client = dict.fromkeys(( 'PASS','JOIN','USER','OPER','MODE','SERVICE','QUIT','SQUIT',
        'PART','TOPIC','NAMES','LIST','INVITE',
        'KICK','PRIVMSG','NOTICE','MOTD','LUSERS','VERSION','STATS','LINKS','TIME','CONNECT',
        'TRACE','ADMIN','INFO','SERVLIST',
        'SQUERY','WHO','WHOIS','WHOWAS','KILL','PING','PONG','ERROR','AWAY','REHASH','DIE','RESTART',
        'SUMMON','USERS','WALLOPS',
        'USERHOST','NICK','ISON'
    ))
   
    def __init__(self):
        self._messages = []
        # Server commandis : prefix - command - params 
        self._sc = {}
        # Client commands : command - params 
        self._cc = {}
        log = logging.getLogger("Processing.Pcap.irc.protocol")

    def _unpack(self, buf):
        """ 
        Extract into a list irc messages of a tcp streams
        @buf: tcp stream data
        """
        try:
            f = cStringIO.StringIO(buf)
            lines = f.readlines()
        except Exception, why:
            log.error("Failed reading tcp stream buffer")
            return False

        for element in lines:
            if re.match('^:',element) != None:
                command = '([a-zA-Z]+|[0-9]{3})'
                params = '(\x20.+)'
                irc_server_msg = re.findall('(^:[\w+.{}!@|()]+\x20)'+command+params,element)
                if irc_server_msg:
                    self._sc['prefix'] = convert_to_printable(irc_server_msg[0][0].strip())
                    self._sc['command'] = convert_to_printable(irc_server_msg[0][1].strip())
                    self._sc['params'] = convert_to_printable(irc_server_msg[0][2].strip())
                    self._sc['type'] = 'server'
                self._messages.append(dict(self._sc))
            else:
                irc_client_msg = re.findall('([a-zA-Z]+\x20)(.+[\x0a\0x0d])',element)
                if irc_client_msg and irc_client_msg[0][0].strip() in self.__methods_client:
                    self._cc['command'] = convert_to_printable(irc_client_msg[0][0].strip())
                    self._cc['params'] = convert_to_printable(irc_client_msg[0][1].strip())
                    self._cc['type'] = 'client'
                self._messages.append(dict(self._cc))
    
    def getClientMessages(self,buf):
        """
        Get irc client commands of tcp streams
        @buf: list of messages
        @return: dictionary of the client messages
        """

        try:
            self._unpack(buf)
        except Exception:
            return None

        entry_cc = []
        for msg in self._messages:
            if msg['type'] == 'client':
                entry_cc.append(msg)     

        return entry_cc

    def getClientMessagesFilter(self,buf,filters):
        """
        Get irc client commands of tcp streams
        @buf: list of messages
        @return: dictionary of the client messages filtered
        """
        try:
            self._unpack(buf)
        except Exception:
            return None

        entry_cc = []

        for msg in self._messages:
            if msg['type'] == 'client' and msg['command'] not in filters:
                entry_cc.append(msg)

        return entry_cc

    def getServerMessages(self,buf):
        """
        Get irc server commands of tcp streams
        @buf: list of messages
        @return: dictionary of server messages
        """

        try:
            self._unpack(buf)
        except Exception:
            return None

        entry_sc = []

        for msg in self._messages:
            if msg['type'] == 'server':
                entry_sc.append(msg)

        return entry_sc

    def getServerMessagesFilter(self,buf,filters):
        """
        Get irc server commands of tcp streams
        @buf: list of messages
        @return: dictionary of server messages filtered
        """
        try:
            self._unpack(buf)
        except Exception:
            return None

        entry_sc = []
        for msg in self._messages:
            if msg['type'] == 'server' and msg['command'] not in filters:
                entry_sc.append(msg)
        
        return entry_sc

    def isthereIRC(self,buf):
        """
        Check if there is irc messages in a stream TCP
        @buf: stream data
        @return: boolean result
        """

        try:
            self._unpack(buf)
            if self._messages:
                return True
            else:
                return False
        except Exception:
            return False
